import { Injectable, Logger, BadRequestException } from "@nestjs/common";
import * as fs from "fs-extra";
import * as path from "node:path";
import { RequsetFileInfoDto } from "src/dto/file";
import { fileTypeFromFile, MimeType } from "file-type";
import { JwtService } from "src/jwt/jwt.service";
import { MediaService } from "src/user/service/media.service";
import type { MediaEntity } from "src/entity";
import { FileDownloadInfo } from "src/common/model";

export type DownloadFileTokenInfo = {
    userId: number;
    filepath: string;
    mime?: MimeType;
};

@Injectable()
export class FileService {
    private readonly logger = new Logger(FileService.name);

    constructor(
        private readonly jwtService: JwtService,
        private readonly mediaService: MediaService,
    ) {}

    async getFileInfo(user: RequsetUser, dto: RequsetFileInfoDto): Promise<FileDownloadInfo> {
        const filepath = dto.filepath;
        if (!fs.existsSync(filepath)) throw new BadRequestException(`文件不存在 : ${filepath}`);

        const stat = await fs.stat(filepath);
        if (stat.isDirectory()) throw new BadRequestException(`这是个文件夹 : ${filepath}`);

        const info = path.parse(filepath);
        const token: DownloadFileTokenInfo = { userId: user.id, filepath };

        let media: MediaEntity;

        if (dto.mime) {
            const filetype = await fileTypeFromFile(filepath);
            if (filetype) token.mime = filetype.mime;

            if (token.mime && (token.mime.startsWith("video") || token.mime.startsWith("audio"))) {
                media = (await this.mediaService.query(user.id, { limit: 1, where: { filepath } }))[0];
            }
        }

        return {
            url: `/file/get/${encodeURIComponent(info.base)}?type=${!token.mime ? "download" : "playback"}&token=${await this.jwtService.generateFileToken(token)}`,
            filename: info.base,
            filesize: stat.size,
            mime: token.mime,
            media,
        };
    }

    verifyToken(token: string) {
        return this.jwtService.verifyFile(token);
    }
}
